package com.atguigu.tingshu.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

	@Autowired
	private MongoTemplate mongoTemplate;
    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public BigDecimal getTrackBreakSecond(Long trackId) {
        //获取用户id
        Long userId = AuthContextHolder.getUserId();

        //构建条件对象
        Criteria criteria = Criteria.where("trackId").is(trackId).and("userId").is(userId);
        //构建查询
        Query query = new Query(criteria);

        //查询
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
        UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);
        if (userListenProcess==null){
            return new BigDecimal(0.00);
        }
        return userListenProcess.getBreakSecond();//存放的秒数
    }

    //TODO 修改播放进程
    @Override
    public void updateListenProcess(UserListenProcessVo userListenProcessVo) {
        //获取用户id
        Long userId = AuthContextHolder.getUserId();

        //构建条件对象
        Criteria criteria = Criteria.where("trackId").is(userListenProcessVo.getTrackId()).and("userId").is(userId);
        //构建查询
        Query query = new Query(criteria);

        //查询
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
        UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);
        if (userListenProcess==null){
            // 第一次来播放 保存
            userListenProcess = new UserListenProcess();
            userListenProcess.setId(ObjectId.get().toString());//文档主键
            userListenProcess.setUserId(userId);
            userListenProcess.setAlbumId(userListenProcessVo.getAlbumId());
            userListenProcess.setTrackId(userListenProcessVo.getTrackId());
            userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
            userListenProcess.setIsShow(1); // 是否暂时 没用到
            userListenProcess.setCreateTime(new Date());
            userListenProcess.setUpdateTime(new Date());
            mongoTemplate.save(userListenProcess, collectionName);
            log.info("保存播放进度到Mongo中成功");
        }else {
            userListenProcess.setCreateTime(new Date());
            userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
            mongoTemplate.save(userListenProcess,collectionName);
            log.info("修改播放进度到Mongo中成功");
        }
        // 5. 修改MySQL中声音/专辑的播放量（异步发送消息给下游专辑微服务更新声音和专辑的播放量）

        // 分布式锁（redis中setifabsent/redisson中lock/mysql/zk ）
        // redis中bitmap结构

        String bitmapKey  = new DateTime().toString("yyyyMMdd") + ":" + userListenProcessVo.getTrackId();
        Boolean setBit = redisTemplate.opsForValue().setBit(bitmapKey, userId, true);
        if (!setBit){
            //同一天同一个用户同一时间只有一条播放量
            //设置一天过期时间
            redisTemplate.expire(bitmapKey,1, TimeUnit.DAYS);
            // 5.1 构建消息对象
            TrackStatMqVo trackStatMqVo = prepareStatMsgDto(userListenProcessVo);
            rabbitService.sendMessage(MqConst.EXCHANGE_TRACK, MqConst.ROUTING_TRACK_STAT_UPDATE, JSONObject.toJSONString(trackStatMqVo));
        }
    }

    //TODO 最近播放声音
    @Override
    public Map<String, Object> getLatelyTrack() {
        Long userId = AuthContextHolder.getUserId();
        // 当前用户最近听的声音
        // 1.构建条件对象
        Criteria criteria = Criteria.where("userId").is(userId);

        // 2.构建查询对象
        Query query = new Query(criteria);

        //3.根据声音修改时间找最大的
        Sort updateTime = Sort.by(Sort.Direction.DESC, "updateTime");
        query.with(updateTime);

        //4.查询
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
        UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

        HashMap<String, Object> map=new HashMap<>();
        map.put("trackId",userListenProcess.getTrackId());
        map.put("albumId",userListenProcess.getAlbumId());
        return map;
    }

    //TODO 构建消息对象
    private TrackStatMqVo prepareStatMsgDto(UserListenProcessVo userListenProcessVo) {
        TrackStatMqVo trackStatMqVo = new TrackStatMqVo();
        trackStatMqVo.setBusinessNo(UUID.randomUUID().toString().replace("-", ""));
        trackStatMqVo.setAlbumId(userListenProcessVo.getAlbumId());
        trackStatMqVo.setTrackId(userListenProcessVo.getTrackId());
        trackStatMqVo.setStatType(SystemConstant.ALBUM_STAT_PLAY);
        trackStatMqVo.setCount(2);

        return trackStatMqVo;
    }
}
